using System;
using System.Windows.Forms;
using EnvDTE;
using Microsoft.WowAddonStudio.Lua.RuntimeService.Tests.Mocks;
using Microsoft.WowAddonStudio.Lua.RuntimeService.WowBench;
using Microsoft.WowAddonStudio.Lua.RuntimeService.WowBench.Resolvers;
using Microsoft.WowAddonStudio.Tests.Common.Mocks;

using NUnit.Framework;

namespace Microsoft.WowAddonStudio.Lua.RuntimeService.Tests.WowBench
{
	[TestFixture]
	public class WoWBenchControllerTest : WoWBenchTestBase
	{
		private WoWBenchController controller;
		private ILuaRuntime runtime;
		private TextBoxBase textBox;

		#region SetUp

		/// <summary>
		/// Tests the fixture set up.
		/// </summary>
		[TestFixtureSetUp]
		public override void TestFixtureSetUp()
		{
			base.TestFixtureSetUp();

			runtime = new LuaRuntime(Provider, new ResolverFactory(Provider), new MockShellHostFactory());

			var props = new MockProperties(DTE, null);

			if (!props.ContainsKey("FullPath"))
				props.Add("FullPath", CreateMockProperty(props, "FullPath", Environment.CurrentDirectory));

			if (!props.ContainsKey("AddonTitle"))
				props.Add("AddonTitle", CreateMockProperty(props, "AddonTitle", "WoWAddOn12"));

			var project = new MockOAProject(DTE, props);

			SimpleTestServiceLocator.Register<EnvDTE.Project>(project);
		}

		/// <summary>
		/// Sets up.
		/// </summary>
		[SetUp]
		public override void SetUp()
		{
			base.SetUp();
			textBox = new RichTextBox();
			controller = new WoWBenchController(runtime);
		}

		#endregion

		#region TearDown

		/// <summary>
		/// Tears down.
		/// </summary>
		[TearDown]
		public override void TearDown()
		{
			base.TearDown();
		}

		#endregion

		#region Tests

		[Test(Description = "")]
		[ExpectedException(typeof (ArgumentNullException))]
		public void Test_Creation()
		{
			controller = new WoWBenchController(null);
		}

		[Test(Description = "")]
		[ExpectedException(typeof(ArgumentNullException))]
		public void Test_InitializeFailed()
		{
			controller.Initialize(null);
		}

		[Test(Description = "")]
		public void Test_Initialize()
		{
			textBox.Text = ".....test......";
			Assert.IsNotNull(controller.CommandHistory);
			Assert.IsInstanceOfType(typeof (CommandHistory), controller.CommandHistory);
			((CommandHistory) controller.CommandHistory).Add(new WoWBenchCommand(null, "Any..."));

			controller.Initialize(textBox);
			Assert.AreEqual(string.Empty, textBox.Text);
			Assert.IsNotNull(controller.CommandHistory.Current.GetCommand());
			Assert.IsNotNull(controller.RuntimeShellHost);
			Assert.IsNotNull(controller.TextOutputWriter);
			Assert.IsNotNull(controller.WowBenchCommand);
			Assert.AreEqual(0, controller.BufferPosition);
		}

		[Test(Description = "")]
		public void Test_LoadWoWBench()
		{
			controller.Initialize(textBox);

			bool result = controller.RunWoWBench();
			Console.WriteLine(textBox.Text);
			Assert.IsTrue(result);
			controller.ExecuteCommand("Test command from Mock.");
		}

		[Test(Description = "")]
		public void Test_LoadWoWBenchAddOn()
		{
			controller.Initialize(textBox);

			bool result = controller.RunWoWBenchAddOn();
			Console.WriteLine(textBox.Text);
			Assert.IsTrue(result);
			controller.ExecuteCommand("Test command from Mock.");
		}

		[Test(Description = "")]
		public void Test_LoadInterpreter()
		{
			controller.Initialize(textBox);

			bool result = controller.RunLuaInterpreter();
			Console.WriteLine(textBox.Text);
			Assert.IsTrue(result);
			controller.ExecuteCommand("Test command from Mock.");
		}

		[Test(Description = "")]
		public void Test_ExecuteCommand()
		{
			const string CONTROL_BREAK = "%BREAK%";

			controller.Initialize(textBox);
			controller.RunLuaInterpreter();
			Assert.AreEqual(string.Empty, controller.ExecuteCommand(String.Empty));
			Assert.AreEqual(1, controller.CommandHistory.Count);

			Assert.AreEqual(null, controller.ExecuteCommand(null));
			Assert.AreEqual(1, controller.CommandHistory.Count);

			Assert.AreEqual("print(10);", controller.ExecuteCommand("print(10);"));
			Assert.AreEqual(2, controller.CommandHistory.Count);

			Assert.AreEqual(CONTROL_BREAK, controller.ExecuteCommand(CONTROL_BREAK));
			Assert.AreEqual(2, controller.CommandHistory.Count);
		}

		#endregion
	}
}